home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 32 / advsys.zip / ADVEXP.C < prev    next >
Text File  |  1986-07-20  |  11KB  |  542 lines

  1. /* advexp.c - expression compiler for adventure games */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8. #include "advdbs.h"
  9.  
  10. /* external routines */
  11. extern SYMBOL *sfind();
  12.  
  13. /* external variables */
  14. extern char t_token[];
  15. extern int t_value;
  16. extern int curobj;
  17. extern char *code;
  18. extern int cptr;
  19.  
  20. /* forward declarations */
  21. int do_cond(),do_and(),do_or(),do_if(),do_while(),do_progn();
  22. int do_setq(),do_return(),do_send(),do_sndsuper();
  23.  
  24. /* opcode tables */
  25. static struct { char *nt_name; int nt_code,nt_args; } *nptr,ntab[] = {
  26.     "not",        OP_NOT,        1,
  27.     "+",        OP_ADD,        2,
  28.     "-",        OP_SUB,        2,
  29.     "*",        OP_MUL,        2,
  30.     "/",        OP_DIV,        2,
  31.     "%",        OP_REM,        2,
  32.     "&",        OP_BAND,    2,
  33.     "|",        OP_BOR,        2,
  34.     "~",        OP_BNOT,    1,
  35.     "<",        OP_LT,        2,
  36.     "=",        OP_EQ,        2,
  37.     ">",        OP_GT,        2,
  38.     "getp",        OP_GETP,    2,
  39.     "setp",        OP_SETP,    3,
  40.     "class",    OP_CLASS,    1,
  41.     "match",    OP_MATCH,    2,
  42.     "print",    OP_PRINT,    1,
  43.     "print-number",    OP_PNUMBER,    1,
  44.     "print-noun",    OP_PNOUN,    1,
  45.     "terpri",    OP_TERPRI,    0,
  46.     "finish",    OP_FINISH,    0,
  47.     "chain",    OP_CHAIN,    0,
  48.     "abort",    OP_ABORT,    0,
  49.     "exit",        OP_EXIT,    0,
  50.     "save",        OP_SAVE,    0,
  51.     "restore",    OP_RESTORE,    0,
  52.     "restart",    OP_RESTART,    0,
  53.     "yes-or-no",    OP_YORN,    0,
  54.     "rand",        OP_RAND,    1,
  55.     "randomize",    OP_RNDMIZE,    0,
  56.     0
  57. };
  58. static struct { char *ft_name; int (*ft_fcn)(); } *fptr,ftab[] = {
  59.     "cond",        do_cond,
  60.     "and",        do_and,
  61.     "or",        do_or,
  62.     "if",        do_if,
  63.     "while",    do_while,
  64.     "progn",    do_progn,
  65.     "setq",        do_setq,
  66.     "return",    do_return,
  67.     "send",        do_send,
  68.     "send-super",    do_sndsuper,
  69.     0
  70. };
  71.  
  72. /* do_expr - compile a subexpression */
  73. do_expr()
  74. {
  75.     int tkn;
  76.  
  77.     switch (token()) {
  78.     case T_OPEN:
  79.     switch (tkn = token()) {
  80.     case T_IDENTIFIER:
  81.         if (in_ntab() || in_ftab())
  82.         break;
  83.     default:
  84.         stoken(tkn);
  85.         do_call();
  86.     }
  87.     break;
  88.     case T_NUMBER:
  89.     do_literal();
  90.     break;
  91.     case T_STRING:
  92.     do_literal();
  93.     break;
  94.     case T_IDENTIFIER:
  95.     do_identifier();
  96.     break;
  97.     default:
  98.     error("Expecting expression");
  99.     }
  100. }
  101.  
  102. /* in_ntab - check for a function in ntab */
  103. int in_ntab()
  104. {
  105.     for (nptr = ntab; nptr->nt_name; ++nptr)
  106.     if (strcmp(t_token,nptr->nt_name) == 0) {
  107.         do_nary(nptr->nt_code,nptr->nt_args);
  108.         return (TRUE);
  109.     }
  110.     return (FALSE);
  111. }
  112.  
  113. /* in_ftab - check for a function in ftab */
  114. int in_ftab()
  115. {
  116.     for (fptr = ftab; fptr->ft_name; ++fptr)
  117.     if (strcmp(t_token,fptr->ft_name) == 0) {
  118.         (*fptr->ft_fcn)();
  119.         return (TRUE);
  120.     }
  121.     return (FALSE);
  122. }
  123.  
  124. /* do_cond - compile the (COND ... ) expression */
  125. do_cond()
  126. {
  127.     int tkn,nxt,end;
  128.  
  129.     /* initialize the fixup chain */
  130.     end = NIL;
  131.  
  132.     /* compile each COND clause */
  133.     while ((tkn = token()) != T_CLOSE) {
  134.     require(tkn,T_OPEN);
  135.     do_expr();
  136.     putcbyte(OP_BRF);
  137.     nxt = putcword(NIL);
  138.     while ((tkn = token()) != T_CLOSE) {
  139.         stoken(tkn);
  140.         do_expr();
  141.     }
  142.     putcbyte(OP_BR);
  143.     end = putcword(end);
  144.     fixup(nxt,cptr);
  145.     }
  146.  
  147.     /* fixup references to the end of statement */
  148.     if (end)
  149.     fixup(end,cptr);
  150.     else
  151.     putcbyte(OP_NIL);
  152. }
  153.  
  154. /* do_and - compile the (AND ... ) expression */
  155. do_and()
  156. {
  157.     int tkn,end;
  158.  
  159.     /* initialize the fixup chain */
  160.     end = NIL;
  161.  
  162.     /* compile each expression */
  163.     while ((tkn = token()) != T_CLOSE) {
  164.     stoken(tkn);
  165.     do_expr();
  166.     putcbyte(OP_BRF);
  167.     end = putcword(end);
  168.     }
  169.  
  170.     /* fixup references to the end of statement */
  171.     if (end)
  172.     fixup(end,cptr);
  173.     else
  174.     putcbyte(OP_NIL);
  175. }
  176.  
  177. /* do_or - compile the (OR ... ) expression */
  178. do_or()
  179. {
  180.     int tkn,end;
  181.  
  182.     /* initialize the fixup chain */
  183.     end = NIL;
  184.  
  185.     /* compile each expression */
  186.     while ((tkn = token()) != T_CLOSE) {
  187.     stoken(tkn);
  188.     do_expr();
  189.     putcbyte(OP_BRT);
  190.     end = putcword(end);
  191.     }
  192.  
  193.     /* fixup references to the end of statement */
  194.     if (end)
  195.     fixup(end,cptr);
  196.     else
  197.     putcbyte(OP_T);
  198. }
  199.  
  200. /* do_if - compile the (IF ... ) expression */
  201. do_if()
  202. {
  203.     int tkn,nxt,end;
  204.  
  205.     /* compile the test expression */
  206.     do_expr();
  207.  
  208.     /* skip around the 'then' clause if the expression is false */
  209.     putcbyte(OP_BRF);
  210.     nxt = putcword(NIL);
  211.  
  212.     /* compile the 'then' clause */
  213.     do_expr();
  214.  
  215.     /* compile the 'else' clause */
  216.     if ((tkn = token()) != T_CLOSE) {
  217.     putcbyte(OP_BR);
  218.     end = putcword(NIL);
  219.     fixup(nxt,cptr);
  220.     stoken(tkn);
  221.     do_expr();
  222.     frequire(T_CLOSE);
  223.     nxt = end;
  224.     }
  225.  
  226.     /* handle the end of the statement */
  227.     fixup(nxt,cptr);
  228. }
  229.  
  230. /* do_while - compile the (WHILE ... ) expression */
  231. do_while()
  232. {
  233.     int tkn,nxt,end;
  234.  
  235.     /* compile the test expression */
  236.     nxt = cptr;
  237.     do_expr();
  238.  
  239.     /* skip around the 'then' clause if the expression is false */
  240.     putcbyte(OP_BRF);
  241.     end = putcword(NIL);
  242.  
  243.     /* compile the loop body */
  244.     while ((tkn = token()) != T_CLOSE) {
  245.     stoken(tkn);
  246.     do_expr();
  247.     }
  248.  
  249.     /* branch back to the start of the loop */
  250.     putcbyte(OP_BR);
  251.     putcword(nxt);
  252.  
  253.     /* handle the end of the statement */
  254.     fixup(end,cptr);
  255. }
  256.  
  257. /* do_progn - compile the (PROGN ... ) expression */
  258. do_progn()
  259. {
  260.     int tkn,n;
  261.  
  262.     /* compile each expression */
  263.     for (n = 0; (tkn = token()) != T_CLOSE; ++n) {
  264.     stoken(tkn);
  265.     do_expr();
  266.     }
  267.  
  268.     /* check for an empty statement list */
  269.     if (n == 0)
  270.     putcbyte(OP_NIL);
  271. }
  272.  
  273. /* do_setq - compile the (SETQ v x) expression */
  274. do_setq()
  275. {
  276.     char name[TKNSIZE+1];
  277.     int n;
  278.  
  279.     /* get the symbol name */
  280.     frequire(T_IDENTIFIER);
  281.     strcpy(name,t_token);
  282.  
  283.     /* compile the value expression */
  284.     do_expr();
  285.  
  286.     /* check for this being a local symbol */
  287.     if ((n = findarg(name)) >= 0)
  288.     code_setargument(n);
  289.     else if ((n = findtmp(name)) >= 0)
  290.     code_settemporary(n);
  291.     else {
  292.     n = venter(name);
  293.     code_setvariable(n);
  294.     }
  295.     frequire(T_CLOSE);
  296. }
  297.  
  298. /* do_return - handle the (RETURN [expr]) expression */
  299. do_return()
  300. {
  301.     int tkn;
  302.  
  303.     /* look for a result expression */
  304.     if ((tkn = token()) != T_CLOSE) {
  305.     stoken(tkn);
  306.     do_expr();
  307.     frequire(T_CLOSE);
  308.     }
  309.  
  310.     /* otherwise, default the result to nil */
  311.     else
  312.     putcbyte(OP_NIL);
  313.  
  314.     /* insert the return opcode */
  315.     putcbyte(OP_RETURN);
  316. }
  317.  
  318. /* do_send - handle the (SEND obj msg [expr]...) expression */
  319. do_send()
  320. {
  321.     /* start searching for the method at the object itself */
  322.     putcbyte(OP_NIL);
  323.  
  324.     /* compile the object expression */
  325.     putcbyte(OP_PUSH);
  326.     do_expr();
  327.  
  328.     /* call the general message sender */
  329.     sender();
  330. }
  331.  
  332. /* do_sndsuper - handle the (SEND-SUPER msg [expr]...) expression */
  333. do_sndsuper()
  334. {
  335.     /* start searching for the method at the current class object */
  336.     code_literal(curobj);
  337.  
  338.     /* pass the message to "self" */
  339.     putcbyte(OP_PUSH);
  340.     code_argument(findarg("self"));
  341.  
  342.     /* call the general message sender */
  343.     sender();
  344. }
  345.  
  346. /* sender - compile an expression to send a message to an object */
  347. sender()
  348. {
  349.     int tkn,n;
  350.     
  351.     /* compile the selector expression */
  352.     putcbyte(OP_PUSH);
  353.     do_expr();
  354.  
  355.     /* compile each argument expression */
  356.     for (n = 2; (tkn = token()) != T_CLOSE; ++n) {
  357.     stoken(tkn);
  358.     putcbyte(OP_PUSH);
  359.     do_expr();
  360.     }
  361.     putcbyte(OP_SEND);
  362.     putcbyte(n);
  363. }
  364.  
  365. /* do_call - compile a function call */
  366. do_call()
  367. {
  368.     int tkn,n;
  369.     
  370.     /* compile the function itself */
  371.     do_expr();
  372.  
  373.     /* compile each argument expression */
  374.     for (n = 0; (tkn = token()) != T_CLOSE; ++n) {
  375.     stoken(tkn);
  376.     putcbyte(OP_PUSH);
  377.     do_expr();
  378.     }
  379.     putcbyte(OP_CALL);
  380.     putcbyte(n);
  381. }
  382.  
  383. /* do_nary - compile nary operator expressions */
  384. do_nary(op,n)
  385.   int op,n;
  386. {
  387.     while (n--) {
  388.     do_expr();
  389.     if (n) putcbyte(OP_PUSH);
  390.     }
  391.     putcbyte(op);
  392.     frequire(T_CLOSE);
  393. }
  394.  
  395. /* do_literal - compile a literal */
  396. do_literal()
  397. {
  398.     code_literal(t_value);
  399. }
  400.  
  401. /* do_identifier - compile an identifier */
  402. do_identifier()
  403. {
  404.     SYMBOL *sym;
  405.     int n;
  406.     
  407.     if (match("t"))
  408.     putcbyte(OP_T);
  409.     else if (match("nil"))
  410.     putcbyte(OP_NIL);
  411.     else if ((n = findarg(t_token)) >= 0)
  412.     code_argument(n);
  413.     else if ((n = findtmp(t_token)) >= 0)
  414.     code_temporary(n);
  415.     else if (sym = sfind(t_token)) {
  416.     if (sym->s_type == ST_VARIABLE)
  417.         code_variable(sym->s_value);
  418.     else
  419.         code_literal(sym->s_value);
  420.     }
  421.     else
  422.     code_literal(oenter(t_token));
  423. }
  424.  
  425. /* code_argument - compile an argument reference */
  426. code_argument(n)
  427.   int n;
  428. {
  429.     putcbyte(OP_ARG);
  430.     putcbyte(n);
  431. }
  432.  
  433. /* code_setargument - compile a set argument reference */
  434. code_setargument(n)
  435.   int n;
  436. {
  437.     putcbyte(OP_ASET);
  438.     putcbyte(n);
  439. }
  440.  
  441. /* code_temporary - compile an temporary reference */
  442. code_temporary(n)
  443.   int n;
  444. {
  445.     putcbyte(OP_TMP);
  446.     putcbyte(n);
  447. }
  448.  
  449. /* code_settemporary - compile a set temporary reference */
  450. code_settemporary(n)
  451.   int n;
  452. {
  453.     putcbyte(OP_TSET);
  454.     putcbyte(n);
  455. }
  456.  
  457. /* code_variable - compile a variable reference */
  458. code_variable(n)
  459.   int n;
  460. {
  461.     if (n < 32)
  462.     putcbyte(OP_XVAR+n);
  463.     else if (n < 256)
  464.     { putcbyte(OP_SVAR); putcbyte(n); }
  465.     else
  466.     { putcbyte(OP_VAR); putcword(n); }
  467. }
  468.  
  469. /* code_setvariable - compile a set variable reference */
  470. code_setvariable(n)
  471.   int n;
  472. {
  473.     if (n < 32)
  474.     putcbyte(OP_XSET+n);
  475.     else if (n < 256)
  476.     { putcbyte(OP_SSET); putcbyte(n); }
  477.     else
  478.     { putcbyte(OP_SET); putcword(n); }
  479. }
  480.  
  481. /* code_literal - compile a literal reference */
  482. code_literal(n)
  483.   int n;
  484. {
  485.     if (n >= 0 && n < 64)
  486.     putcbyte(OP_XPLIT+n);
  487.     else if (n < 0 && n > -64)
  488.     putcbyte(OP_XNLIT-n);
  489.     else if (n >= 64 && n < 256)
  490.     { putcbyte(OP_SPLIT); putcbyte(n); }
  491.     else if (n <= -64 && n > -256)
  492.     { putcbyte(OP_SNLIT); putcbyte(-n); }
  493.     else
  494.     { putcbyte(OP_LIT); putcword(n); }
  495. }
  496.  
  497. /* do_op - insert an opcode and look for closing paren */
  498. do_op(op)
  499.   int op;
  500. {
  501.     putcbyte(op);
  502.     frequire(T_CLOSE);
  503. }
  504.  
  505. /* putcbyte - put a code byte into data space */
  506. int putcbyte(b)
  507.   int b;
  508. {
  509.     if (cptr < CMAX)
  510.     code[cptr++] = b;
  511.     else
  512.     error("insufficient code space");
  513.     return (cptr-1);
  514. }
  515.  
  516. /* putcword - put a code word into data space */
  517. int putcword(w)
  518.   int w;
  519. {
  520.     putcbyte(w);
  521.     putcbyte(w >> 8);
  522.     return (cptr-2);
  523. }
  524.  
  525. /* fixup - fixup a reference chain */
  526. fixup(chn,val)
  527.   int chn,val;
  528. {
  529.     int hval,nxt;
  530.  
  531.     /* store the value into each location in the chain */
  532.     for (hval = val >> 8; chn != NIL; chn = nxt) {
  533.     if (chn < 0 || chn > CMAX-2)
  534.         return;
  535.     nxt = (code[chn] & 0xFF) | (code[chn+1] << 8);
  536.     code[chn] = val;
  537.     code[chn+1] = hval;
  538.     }
  539. }
  540.  
  541.                                                                                                                             
  542.